package com.yaolonga.itfc.manager.win;

import com.yaolonga.itfc.manager.core.*;
import com.yaolonga.itfc.manager.core.exception.CmdExecuteException;
import com.yaolonga.itfc.manager.core.wifi.*;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author: yaolong
 * @CreateTime: 2024-10-17  10:23
 * @Description: windows网卡信息提供者
 * @Version: 1.0
 */
@Slf4j
public class WinNetworkInterfaceManager extends AbstractNetworkInterfaceManager {
    private final String dhcp = getLangConfValue("dhcp", String.class);
    private final String dhcpServer = getLangConfValue("dhcpServer", String.class);
    private final String ip = getLangConfValue("ip", String.class);
    private final String autoIp = getLangConfValue("autoIp", String.class);
    private final String mask = getLangConfValue("mask", String.class);
    private final String gateway = getLangConfValue("gateway", String.class);
    private final String dns = getLangConfValue("dns", String.class);
    private final String mac = getLangConfValue("mac", String.class);
    private final String description = getLangConfValue("description", String.class);
    private final String firstChoice = getLangConfValue("firstChoice", String.class);
    private final String ipV6 = getLangConfValue("ipV6", String.class);
    private final String mediaState = getLangConfValue("mediaState", String.class);
    private final String mediaDisconnect = getLangConfValue("mediaDisconnect", String.class);


    // 路由相关
    private final String persistentRoutes = getLangConfValue("router.persistentRoutes", String.class);
    private final String activeRoutes = getLangConfValue("router.activeRoutes", String.class);
    private final String interfaceList = getLangConfValue("router.interfaceList", String.class);
    private final String none = getLangConfValue("router.none", String.class);
    private final String ipv4RouteTable = getLangConfValue("router.ipv4RouteTable", String.class);
    private final String onLink = getLangConfValue("router.onLink", String.class);
    private final String networkDestination = getLangConfValue("router.networkDestination", String.class);
    private final String netmask = getLangConfValue("router.netmask", String.class);
    private final String routeGateway = getLangConfValue("router.routeGateway", String.class);
    private final String interface_ = getLangConfValue("router.interface", String.class);
    private final String metric = getLangConfValue("router.metric", String.class);
    private final String networkAddress = getLangConfValue("router.networkAddress", String.class);

    // wifi相关
    private final String interfaceName = getLangConfValue("wifi.interfaceName", String.class);
    private final String ssidNetworkType = getLangConfValue("wifi.ssidNetworkType", String.class);

    private final String secureType = getLangConfValue("wifi.secureType", String.class);
    private final String wifiLinkInfoSecurityWPA2 = getLangConfValue("wifi.wifiLinkInfoSecurityWPA2", String.class);
    private final String wifiLinkInfoSecurityWPA3 = getLangConfValue("wifi.wifiLinkInfoSecurityWPA3", String.class);
    private final String wifiLinkInfoSecurityOpen = getLangConfValue("wifi.wifiLinkInfoSecurityOpen", String.class);


    private final String encipher = getLangConfValue("wifi.encipher", String.class);
    private final String signal = getLangConfValue("wifi.signal", String.class);
    private final String radioType = getLangConfValue("wifi.radioType", String.class);
    private final String channel = getLangConfValue("wifi.channel", String.class);
    private final String thereAreCurrently = getLangConfValue("wifi.thereAreCurrently", String.class);
    private final String waveBand = getLangConfValue("wifi.waveBand", String.class);
    private final String keyContent = getLangConfValue("wifi.keyContent", String.class);
    private final String securitySettings = getLangConfValue("wifi.securitySettings", String.class);
    private final String profileName = getLangConfValue("wifi.profileName", String.class);
    private final String manualConnection = getLangConfValue("wifi.manualConnection", String.class);
    private final String connectionMode = getLangConfValue("wifi.connectionMode", String.class);
    private final String SSIDName = getLangConfValue("wifi.SSIDName", String.class);
    private final String bearerNetworkState = getLangConfValue("wifi.bearerNetworkState", String.class);
    private final String wifiItfcDescription = getLangConfValue("wifi.wifiItfcDescription", String.class);
    private final String physicalAddress = getLangConfValue("wifi.physicalAddress", String.class);
    private final String wifiLinkState = getLangConfValue("wifi.wifiLinkState", String.class);

    private final String wifiLinkDisConStateValue = getLangConfValue("wifi.wifiLinkDisConStateValue", String.class);
    private final String wifiLinkConStateValue = getLangConfValue("wifi.wifiLinkConStateValue", String.class);
    private final String wifiLinkInfoPwd = getLangConfValue("wifi.wifiLinkInfoPwd", String.class);
    private final String wifiLinkMode = getLangConfValue("wifi.wifiLinkMode", String.class);
    private final String wifiLinkConfFile = getLangConfValue("wifi.wifiLinkConfFile", String.class);
    private final String wifiLinkInfoItfcName = getLangConfValue("wifi.wifiLinkInfoItfcName", String.class);
    private final String wifiLinkInfoWaveBand = getLangConfValue("wifi.wifiLinkInfoWaveBand", String.class);
    private final String wifiLinkInfoChannel = getLangConfValue("wifi.wifiLinkInfoChannel", String.class);


    // wifi相关
    @Override
    public PlatformType getPlatformType() {
        return PlatformType.windows;
    }

    @Override
    public SystemType getSystemType() {
        return SystemType.win;
    }

    /**
     * 获取网络配置输入流
     */
    protected InputStream getNetConfInputStream() {
        return execCmd("ipconfig /all").getInputStream();
    }

    @Override
    public List<NetworkInterfaceInfo> getNetworkInterfaceInfos() {
        List<NetworkInterfaceInfo> netInfos = new ArrayList<>();
        InputStream inputStream = getNetConfInputStream();
        if (inputStream != null) {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, getCharset()));
            String line;
            try {
                NetworkInterfaceInfo networkInterfaceInfo = new NetworkInterfaceInfo();
                // 是否忽略行
                boolean ignoreLine = false;
                while ((line = bufferedReader.readLine()) != null) {
                    // 空白行忽略
                    if (line.trim().isEmpty()) {
                        continue;
                    }
                    networkInterfaceInfo = parseEthNetworkInterfaceInfo(bufferedReader, line, networkInterfaceInfo, netInfos);

                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
                return Collections.emptyList();
            }
        }

        Map<NetworkInterface, LinkedHashSet<InetAddress>> nicIpV4Map = getWinNicAdreesMap();

        // 获取路由表
        List<NetRoute> netIp4Routes = getNetIp4Routes();

        return nicIpV4Map.keySet().stream()
                .map(itfc -> {
                    try {
                        String id = itfc.getName();
                        String description = itfc.getDisplayName();
                        // 通过描述信息过滤掉无效的网卡
                        NetworkInterfaceInfo networkInterfaceInfo = netInfos
                                .stream()
                                .filter(i -> i.getDescription().equals(description)).findFirst().get();
                        // 设置网卡索引
                        networkInterfaceInfo.setIfIndex(itfc.getIndex());
                        List<NetRoute> routes = netIp4Routes.stream().filter(i ->
                                        networkInterfaceInfo.getIp().stream().anyMatch(ip -> ip.getIp().equals(i.getIp())) ||
                                                (Objects.nonNull(networkInterfaceInfo.getGateway()) && networkInterfaceInfo.getGateway().equals(i.getGateway()))
                                )
                                .peek(i -> {
                                    i.setInterfaceName(networkInterfaceInfo.getName());
                                    i.setIfIndex(networkInterfaceInfo.getIfIndex());
                                }).collect(Collectors.toList());

                        networkInterfaceInfo.setRoutes(routes);
                        return networkInterfaceInfo;
                    } catch (Exception e) {
                        return null;
                    }
                }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    @Override
    public NetworkInterfaceInfo getNetworkInterfaceInfo(String interfaceName) {
        return getNetworkInterfaceInfos().stream().filter(i -> i.getId().equals(interfaceName)).findFirst().orElse(null);
    }

    @Override
    public String configDhcpIpAddress(String interfaceName) {
        String result = execCmdAndReturn("netsh interface ip set address name=\"" + interfaceName + "\" dhcp");
        log.debug("配置dhcp ip结果 {}", result);
        return result;
    }

    @Override
    public String configDhcpDnsAddress(String interfaceName) {
        String result = execCmdAndReturn("netsh interface ip set dns name=\"" + interfaceName + "\" dhcp");
        log.debug("配置dhcp dns结果 {}", result);
        return result;
    }

    @Override
    public String configStaticIpAddress(String interfaceName, String ip, String mask, String gateway) {
        String result = execCmdAndReturn("netsh interface ip set address name=\"" + interfaceName + "\" static " + ip + " " + mask + " " + gateway);
        log.debug("配置静态ip结果 {}", result);
        return result;
    }

    @Override
    public String configStaticDnsAddress(String interfaceName, String dnsAddress) {
        String result = execCmdAndReturn("netsh interface ip set dns \"" + interfaceName + "\" static " + dnsAddress + " primary");
        log.debug("配置静态dns结果 {}", result);
        return result;
    }

    @Override
    public String addDnsAddress(String interfaceName, String dnsAddress, int index) {
        String result = execCmdAndReturn("netsh interface ip add dns name=\"" + interfaceName + "\" addr=" + dnsAddress + " index=" + index);
        log.debug("添加dns结果 {}", result);
        return result;
    }

    @Override
    public String addDnsAddress(String interfaceName, String dnsAddress) {
        String result = execCmdAndReturn("netsh interface ip add dns name=\"" + interfaceName + "\" addr=" + dnsAddress);
        log.debug("添加dns结果 {}", result);
        return result;
    }


    @Override
    public String delDnsAddress(String interfaceName, String dnsAddress) {
        String s = execCmdAndReturn("netsh interface ip delete dns name=\"" + interfaceName + "\" addr=" + dnsAddress);
        log.debug("删除dns结果 {}", s);
        return s;
    }

    @Override
    public String addRoute(NetRoute route) {
        route.validate();
        List<String> cmdList = new ArrayList<>();
        cmdList.add("route");
        if (NetRouteType.PERMANENT_ROUTE.equals(route.getType())) {
            cmdList.add("-p");
        }
        cmdList.add("add");
        cmdList.add(route.getTarget());
        if (null != route.getMask()) {
            cmdList.add("mask");
            cmdList.add(route.getMask());
        }
        cmdList.add(route.getGateway());

        if (null != route.getMetric()) {
            cmdList.add("metric");
            cmdList.add(route.getMetric());
        }

        if (null != route.getIfIndex()) {
            cmdList.add("if");
            cmdList.add(route.getIfIndex().toString());
        }
        log.debug("执行命令 {}", cmdList);
        return execCmdAndReturn(cmdList);
    }

    /**
     * CHANGE 只用于修改网关和/或跃点数。
     *
     * @param route 路由配置
     * @return 结果
     */
    @Override
    public String changeRoute(NetRoute route) {
        route.validate();
        List<String> cmdList = new ArrayList<>();
        cmdList.add("route");
        cmdList.add("change");
        cmdList.add(route.getTarget());
        cmdList.add("mask");
        cmdList.add(route.getMask());
        cmdList.add(route.getGateway());
        if (null != route.getMetric()) {
            cmdList.add("metric");
            cmdList.add(route.getMetric());
        }
        cmdList.add("if");
        cmdList.add(route.getIfIndex().toString());
        log.debug("执行命令 {}", cmdList);
        return execCmdAndReturn(cmdList);
    }

    @Override
    public String delRoute(NetRoute route) {
        route.validate();
        List<String> cmdList = new ArrayList<>();
        cmdList.add("route");
        cmdList.add("delete");
        cmdList.add(route.getTarget());
        cmdList.add("mask");
        cmdList.add(route.getMask());
        cmdList.add(route.getGateway());
        cmdList.add("if");
        cmdList.add(route.getIfIndex().toString());
        log.debug("执行命令 {}", cmdList);
        return execCmdAndReturn(cmdList);
    }

    @Override
    public WifiScanInfo scanWifiInfo(String interfaceName) {
        List<String> cmdList = getWifiBasicCmds();
        cmdList.add("show");
        cmdList.add("networks");
        cmdList.add("bssid");
        cmdList.add("interface=" + interfaceName);

        log.debug("执行扫描wifi指令 {}", cmdList);
        WifiScanInfo wifiScanInfo = new WifiScanInfo();
        wifiScanInfo.setInterfaceName(interfaceName);
        Process process = execCmd(cmdList);

        InputStream inputStream = process.getInputStream();

        List<SSIDInfo> ssidList = wifiScanInfo.getSsidList();


        if (inputStream != null) {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, getCharset()));
            String line;
            try {
                int currenLine = 0;

                SSIDInfo ssidInfo = null;
                BSSIDInfo bssidInfo = null;
                while ((line = bufferedReader.readLine()) != null) {
                    // 空白行忽略
                    if (line.trim().isEmpty()) {
                        continue;
                    }

                    currenLine = currenLine + 1;
                    if (currenLine == 1 && !line.trim().startsWith(this.interfaceName)) {
                        throw new RuntimeException(line);
                    }

                    if (currenLine == 2 && !line.trim().startsWith(thereAreCurrently)) {
                        throw new RuntimeException(line);
                    }

                    if (currenLine > 2) {
                        line = line.trim();
                        if (line.startsWith("SSID")) {
                            if (ssidInfo != null) {
                                ssidList.add(ssidInfo);
                            }
                            ssidInfo = new SSIDInfo();
                            ssidInfo.setInterfaceName(interfaceName);
                            String[] s = line.split(": ");
                            if (s.length >= 2) {
                                String ssid = s[1].trim();
                                ssidInfo.setSsid(ssid);
                            }
                            continue;
                        }

                        if (Objects.nonNull(ssidInfo)) {
                            if (line.startsWith(ssidNetworkType)) {
                                String[] type = line.split(": ");
                                String networkType = type[1].trim();
                                ssidInfo.setNetworkType(networkType);
                                continue;
                            }
                            if (line.startsWith(secureType)) {
                                String[] type = line.split(": ");
                                String v = type[1].trim();
                                WifiSecureType wifiSecureType = convertSecurityType(v);
                                ssidInfo.setSecureType(wifiSecureType.name());
                                continue;
                            }
                            if (line.startsWith(encipher)) {
                                String[] type = line.split(": ");
                                String v = type[1].trim();
                                ssidInfo.setEncryption(v);
                                continue;
                            }

                            if (line.startsWith("BSSID")) {

                                bssidInfo = new BSSIDInfo();
                                bssidInfo.setSsid(ssidInfo.getSsid());
                                String[] type = line.split(": ");
                                if (type.length >= 2) {
                                    String v = type[1].trim();
                                    bssidInfo.setBssid(v);
                                }
                                continue;
                            }

                            if (Objects.nonNull(bssidInfo)) {
                                if (line.startsWith(signal)) {
                                    String[] type = line.split(": ");
                                    String v = type[1].trim();
                                    bssidInfo.setSignal(v);
                                    continue;
                                }
                                if (line.startsWith(radioType)) {
                                    String[] type = line.split(": ");
                                    String v = type[1].trim();
                                    bssidInfo.setMode(v);
                                    continue;
                                }
                                if (line.startsWith(waveBand)) {
                                    String[] type = line.split(": ");
                                    String v = type[1].trim();
                                    bssidInfo.setWaveBand(v);
                                    continue;
                                }
                                if (line.startsWith(channel)) {
                                    String[] type = line.split(": ");
                                    String v = type[1].trim();
                                    bssidInfo.setChannel(v);
                                    ssidInfo.getBssid().add(bssidInfo);
                                }
                            }

                        }

                    }

                }
                ssidList.add(ssidInfo);
            } catch (IOException e) {
                log.error(e.getMessage(), e);
                throw new RuntimeException(e);
            }
        }

        return wifiScanInfo;

    }

    private static List<String> getWifiBasicCmds() {
        List<String> cmdList = new ArrayList<>();
        cmdList.add("netsh");
        cmdList.add("wlan");
        return cmdList;
    }


    @Override
    public List<WifiLinkInfo> getWifiLinkInfos() {
        List<String> wifiBasicCmds = getWifiBasicCmds();
        wifiBasicCmds.add("show");
        wifiBasicCmds.add("interfaces");
        Process process = execCmd(wifiBasicCmds);
        InputStream inputStream = process.getInputStream();
        List<WifiLinkInfo> wifiLinkInfos = new ArrayList<>();

        try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, getCharset()))) {
            String line;
            WifiLinkInfo wifiLinkInfo = null;
            int currentLine = 0;
            while ((line = br.readLine()) != null) {
                // 空白行忽略
                if (line.trim().isEmpty()) {
                    continue;
                }
                currentLine++;

                // 第一行忽略
                if (currentLine == 1) {
                    continue;
                }


                line = line.trim();
                if (line.startsWith(this.wifiLinkInfoItfcName)) {
                    wifiLinkInfo = new WifiLinkInfo();
                    String[] split = line.split(": ");
                    String interfaceName = split[1].trim();
                    wifiLinkInfo.setInterfaceName(interfaceName);
                }
                if (Objects.nonNull(wifiLinkInfo)) {
                    if (line.startsWith(this.wifiItfcDescription)) {
                        String[] split = line.split(": ");
                        String description = split[1].trim();
                        wifiLinkInfo.setDescription(description);
                        continue;
                    }
                    if (line.startsWith(this.physicalAddress)) {
                        String[] split = line.split(": ");
                        String mac = split[1].trim();
                        wifiLinkInfo.setMac(mac);
                    }

                    if (line.startsWith(this.wifiLinkState)) {
                        String[] split = line.split(": ");
                        String state = split[1].trim();
                        if (this.wifiLinkConStateValue.equals(state)) {
                            wifiLinkInfo.setState(ConState.connected);
                        } else {
                            wifiLinkInfo.setState(ConState.disconnect);
                        }
                        continue;
                    }

                    if (line.startsWith("SSID")) {
                        String[] split = line.split(": ");
                        if (split.length >= 2) {
                            String ssid = split[1].trim();
                            wifiLinkInfo.setSsid(ssid);
                        }
                        continue;
                    }

                    if (line.startsWith("BSSID")) {
                        String[] split = line.split(": ");
                        String bssid = split[1].trim();
                        wifiLinkInfo.setBssid(bssid);
                        continue;
                    }

                    if (line.startsWith(this.wifiLinkInfoPwd)) {
                        String[] split = line.split(": ");
                        String encryption = split[1].trim();
                        wifiLinkInfo.setEncryption(encryption);
                        continue;
                    }

                    if (line.startsWith(this.signal)) {
                        String[] split = line.split(": ");
                        String signal = split[1].trim();
                        wifiLinkInfo.setSignal(signal);
                        continue;
                    }

                    if (line.startsWith(wifiLinkMode)) {
                        String[] split = line.split(": ");
                        String mode = split[1].trim();
                        wifiLinkInfo.setMode(mode);
                        continue;
                    }

                    if (line.startsWith(this.wifiLinkInfoChannel)) {
                        String[] split = line.split(": ");
                        String channel = split[1].trim();
                        wifiLinkInfo.setChannel(channel);
                        continue;
                    }

                    if (line.startsWith(this.wifiLinkInfoWaveBand)) {
                        String[] split = line.split(": ");
                        String waveBand = split[1].trim();
                        wifiLinkInfo.setWaveBand(waveBand);
                        continue;
                    }

                    if (line.startsWith(this.secureType)) {
                        String[] split = line.split(": ");
                        String secureType = split[1].trim();
                        WifiSecureType wifiSecureType = convertSecurityType(secureType);
                        wifiLinkInfo.setSecureType(wifiSecureType.name());
                        continue;
                    }

                    if (line.startsWith(this.wifiLinkConfFile)) {
                        String[] split = line.split(": ");
                        String f = split[1].trim();
                        wifiLinkInfo.setConfigFile(f);
                        continue;
                    }

                    if (line.startsWith(this.bearerNetworkState)) {
                        wifiLinkInfos.add(wifiLinkInfo);
                        continue;
                    }
                }

            }
            return wifiLinkInfos;
        } catch (IOException e) {

        }

        return Collections.emptyList();
    }

    @Override
    public WifiLinkConf getWifiConf(String interfaceName, String profileName) {
        return getWifiProfile(interfaceName, profileName);
    }

    private WifiLinkConf getWifiProfile(String interfaceName, String profileName) {
//        profileName 空格转义
        List<String> wifiBasicCmds = getWifiBasicCmds();
        wifiBasicCmds.add("show");
        wifiBasicCmds.add("profiles");
        wifiBasicCmds.add("name=" + profileName);
        wifiBasicCmds.add("interface=" + interfaceName);
        wifiBasicCmds.add("key=clear");
        Process process = execCmd(wifiBasicCmds);
        InputStream inputStream = process.getInputStream();


        try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, getCharset()))) {

            StringBuilder res = new StringBuilder();
            String line;
            WifiLinkConf wifiLinkConf = null;
            while ((line = br.readLine()) != null) {
                // 空白行忽略
                if (line.trim().isEmpty()) {
                    continue;
                }
                res.append(line);
                line = line.trim();
                if (line.startsWith(this.profileName)) {
                    wifiLinkConf = new WifiLinkConf();
                    wifiLinkConf.setInterfaceName(interfaceName);
                    wifiLinkConf.setName(profileName);
                    continue;
                }
                if (Objects.nonNull(wifiLinkConf)) {
                    if (line.startsWith(connectionMode)) {
                        String[] s = line.split(": ");
                        String mode = s[1].trim();
                        if (mode.equalsIgnoreCase(manualConnection)) {
                            wifiLinkConf.setAutoConnection(false);
                        } else {
                            wifiLinkConf.setAutoConnection(true);
                        }
                        continue;
                    }

                    if (line.startsWith(secureType)) {
                        String[] s = line.split(": ");
                        String v = s[1].trim();
                        WifiSecureType wifiSecureType = convertSecurityType(v);
                        wifiLinkConf.setSecureType(wifiSecureType.name());
                        continue;
                    }
                    if (line.startsWith(SSIDName)) {
                        String[] s = line.split(":");
                        String v = s[1].trim();
                        v = v.replaceAll("\"", "");
                        v = v.replaceAll("“", "");
                        v = v.replaceAll("”", "");
                        wifiLinkConf.setSsid(v);
                        continue;
                    }

                    if (line.startsWith(keyContent)) {
                        String[] s = line.split(": ");
                        String v = s[1].trim();
                        wifiLinkConf.setPassword(v);
                        continue;
                    }
                }
            }
            return wifiLinkConf;
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }


    @Override
    public String connectWifi(WifiLinkConf wifiLinkConf) {
        try {

            String profileName = wifiLinkConf.getName();
            if (profileName == null || profileName.isEmpty()) {
                profileName = wifiLinkConf.getSsid();
                wifiLinkConf.setName(profileName);
            }

            if (wifiLinkConf.getSecureType() == null && wifiLinkConf.getPassword() == null) {
                wifiLinkConf.setSecureType(WifiSecureType.OPEN.name());
            }

            WifiLinkConf wifiProfile = getWifiProfile(wifiLinkConf.getInterfaceName(), wifiLinkConf.getName());
            if (Objects.isNull(wifiProfile)) {
                // 配置文件不存在，创建配置文件
                setWifiConf(wifiLinkConf);
            } else {
                if (!WifiSecureType.OPEN.name().equals(wifiLinkConf.getSecureType()) &&
                        (!wifiProfile.getPassword().equals(wifiLinkConf.getPassword()))
                ) {
                    // 更新配置文件 (删除配置，创建新配置)
                    delWifiConf(wifiLinkConf.getInterfaceName(), profileName);
                    // 创建配置文件
                    setWifiConf(wifiLinkConf);
                }
            }
            List<String> wifiBasicCmds = getWifiBasicCmds();
            wifiBasicCmds.add("connect");
            if (null != wifiLinkConf.getSsid() && !wifiLinkConf.getSsid().isEmpty()) {
                wifiBasicCmds.add("ssid=" + wifiLinkConf.getSsid());
            }
            wifiBasicCmds.add("name=" + profileName);
            wifiBasicCmds.add("interface=" + wifiLinkConf.getInterfaceName());
            String res = execCmdAndReturn(wifiBasicCmds);
            log.debug("连接wifi成功：{}", res);
            return res;
        } catch (Exception e) {
            log.error("连接wifi异常：{}", e.getMessage(), e);
            throw new CmdExecuteException("连接wifi异常：" + e.getMessage(), e);
        }
    }

    @Override
    public String disconnectWifi(String interfaceName) {
        List<String> wifiBasicCmds = getWifiBasicCmds();
        wifiBasicCmds.add("disconnect");
        wifiBasicCmds.add("interface=" + interfaceName);
        return execCmdAndReturn(wifiBasicCmds);
    }

    @Override
    public String forgetWifi(String interfaceName, String profileName) {
        String s1 = disconnectWifi(interfaceName);
        String s = delWifiConf(interfaceName, profileName);
        log.debug("忘记wifi成功： {}", s);
        return String.format("disconnect: %s \n del profile: %s", s1, s);
    }

    @Override
    public String setWifiConf(WifiLinkConf wifiLinkConf) {
        File file = null;
        if (WifiSecureType.OPEN.name().equals(wifiLinkConf.getSecureType())) {
            file = WifiHelper.generateWinWifiProfileFile(wifiLinkConf.getName(), wifiLinkConf.getSsid(), wifiLinkConf.isAutoConnection());
        } else {
            file = WifiHelper.generateWinWifiProfileFile(wifiLinkConf.getName(), wifiLinkConf.getSsid(), wifiLinkConf.getPassword(), wifiLinkConf.isAutoConnection());
        }
        List<String> wifiBasicCmds = getWifiBasicCmds();
        wifiBasicCmds.add("add");
        wifiBasicCmds.add("profile");
        wifiBasicCmds.add("filename=" + file.getAbsolutePath());
        wifiBasicCmds.add("interface=" + wifiLinkConf.getInterfaceName());
        String res = execCmdAndReturn(wifiBasicCmds);
        // 删除临时文件
        file.deleteOnExit();
        log.debug("设置wifi配置文件成功： {}", res);
        return res;
    }

    @Override
    public String delWifiConf(String interfaceName, String profileName) {
        List<String> wifiBasicCmds = getWifiBasicCmds();
        wifiBasicCmds.add("delete");
        wifiBasicCmds.add("profile");
        wifiBasicCmds.add("name=" + profileName);
        String s = execCmdAndReturn(wifiBasicCmds);
        log.debug("删除wifi配置文件成功： {}", s);
        return s;
    }

    @Override
    public String enableWifi(String interfaceName) {
        List<String> cmds = new ArrayList<>();
        cmds.add("netsh");
        cmds.add("interface");
        cmds.add("set");
        cmds.add("interface");
        cmds.add(interfaceName);
        cmds.add("enabled");
        String res = execCmdAndReturn(cmds);
        log.debug("启用wifi： {}", res);
        return res;
    }

    @Override
    public String disableWifi(String interfaceName) {
        List<String> cmds = new ArrayList<>();
        cmds.add("netsh");
        cmds.add("interface");
        cmds.add("set");
        cmds.add("interface");
        cmds.add(interfaceName);
        cmds.add("disable");
        String res = execCmdAndReturn(cmds);
        log.debug("禁用用wifi： {}", res);
        return res;
    }


    private NetworkInterfaceInfo parseEthNetworkInterfaceInfo(BufferedReader bufferedReader, String line, NetworkInterfaceInfo networkInterfaceInfo, List<NetworkInterfaceInfo> netInfos) {
        // 如果当前行第一个字符以空格开始解析
        if (line.startsWith(" ")) {
            parseLine(bufferedReader, line, networkInterfaceInfo);
        } else {
            if (networkInterfaceInfo.getName() != null && !networkInterfaceInfo.getName().trim().isEmpty()) {
                if (networkInterfaceInfo.getDescription() != null && !networkInterfaceInfo.getDescription().isEmpty()) {
                    netInfos.add(networkInterfaceInfo);
                }
                networkInterfaceInfo = new NetworkInterfaceInfo();
            }

            // 截取第一个空格开始后的所有字符串
            networkInterfaceInfo.setName(line.trim().split(":")[0].substring(line.indexOf(" ") + 1));

//            networkInterfaceInfo.setName((line.trim().split(":")[0]).split(" ")[1]);
            networkInterfaceInfo.setId(networkInterfaceInfo.getName());
            if (networkInterfaceInfo.getName().equals("WLAN")){
                networkInterfaceInfo.setType(InterfaceType.wifi);
            } else {
                networkInterfaceInfo.setType(InterfaceType.eth);
            }
        }
        return networkInterfaceInfo;
    }

    private void parseLine(BufferedReader bufferedReader, String line, NetworkInterfaceInfo networkInterfaceInfo) {
        String trimLine = line.trim();
        String[] split = line.split(": ");
        try {
            if (null != dhcp && trimLine.startsWith(dhcp)) {
                String value = split[1];
                Boolean state = getLangConfValue(value, Boolean.class);
                networkInterfaceInfo.setDhcp(state);
            }

            if (null != dhcpServer && trimLine.startsWith(dhcpServer)) {
                String value = split[1];
                networkInterfaceInfo.setDhcpServer(value);
            }

            if ((null != ip && trimLine.startsWith(ip)) || (autoIp != null && trimLine.startsWith(autoIp))) {
                String value = split[1];
                addAddress(bufferedReader, value, networkInterfaceInfo, networkInterfaceInfo::addIp);
            }

            if (null != ipV6 && trimLine.startsWith(ipV6)) {
                String value = split[1];
                addAddress(bufferedReader, value, networkInterfaceInfo, networkInterfaceInfo::addIpV6);
            }

            if (null != mask && trimLine.startsWith(mask)) {
                String value = split[1];
                networkInterfaceInfo.setMask(value);
            }

            if (null != gateway && trimLine.startsWith(gateway)) {
                String value = split[1];

                addAddress(bufferedReader, value, networkInterfaceInfo, info -> {
                    // 忽略ipv6网关
                    if (!info.getIp().contains(":")) {
                        networkInterfaceInfo.setGateway(info.getIp());
                    }
                });

            }

            if (null != mediaState && trimLine.startsWith(mediaState)) {
                String value = split[1];
                networkInterfaceInfo.setState(!value.equals(mediaDisconnect));
            }

            if (null != dns && trimLine.startsWith(dns)) {
                String value = split[1];
                addAddress(bufferedReader, value, networkInterfaceInfo, networkAddress -> {
                    // 忽略ipv6
                    if (!networkAddress.getIp().contains(":")) {
                        if (networkInterfaceInfo.getDns().isEmpty()) {
                            networkAddress.setFirstChoice(true);
                        }
                        networkInterfaceInfo.addDns(networkAddress);
                    }

                });
            }

            if (null != mac && trimLine.startsWith(mac)) {
                String value = split[1];
                networkInterfaceInfo.setMac(value);
            }

            if (null != description && trimLine.startsWith(description)) {
                String value = split[1];
                networkInterfaceInfo.setDescription(value);
            }

        } catch (Exception ignored) {
        }
    }

    private void addAddress(BufferedReader bufferedReader, String value, NetworkInterfaceInfo networkInterfaceInfo, Consumer<NetworkAddress> call) {
        // 原始值
        String value2 = value;
        // 去掉 (首选)
        value = value.replace(firstChoice, "").trim();
        // 原始值和去掉首选值相同则认为是非首选
        if (value2.equals(value)) {
            // 非首选
            call.accept(NetworkAddress.of(value, false));
        } else {
            call.accept(NetworkAddress.of(value, true));
        }

        try {
            String line;
            while ((line = bufferedReader.readLine()) != null) {

                if (!line.startsWith(" ") || line.contains(". :")) {
                    parseLine(bufferedReader, line, networkInterfaceInfo);
                    break;
                }
                String value3 = line.trim();
                // 去掉 (首选)
                value = value3.replace(firstChoice, "").trim();
                // 原始值和去掉首选值相同则认为是非首选
                if (value.equals(value3)) {
                    // 非首选
                    call.accept(NetworkAddress.of(value, false));
                } else {
                    call.accept(NetworkAddress.of(value, true));
                }
            }
        } catch (IOException e) {

        }
    }


    /***
     * 获取路由信息
     * @return 路由信息
     */
    private List<NetRoute> getNetIp4Routes() {

        // 网卡映射
        Map<String, NetworkInterface> netMap = new HashMap<>();

        List<NetRoute> routes = new ArrayList<>();
        InputStream inputStream = execCmd("route print -4").getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, getCharset()));
        String line;
        try {
            // 活动路由解析标志
            boolean activeRouteParseFlag = false;
            boolean persistentRouteParseFlag = false;

            while ((line = bufferedReader.readLine()) != null) {
                // 空白行忽略
                if (line.trim().isEmpty()) {
                    continue;
                }

                line = line.trim();


                if (line.startsWith(activeRoutes)) {
                    activeRouteParseFlag = true;
                    continue;
                }

                if (line.startsWith(persistentRoutes)) {
                    persistentRouteParseFlag = true;
                    continue;
                }

                // 如果激活标志为true,且为===开始则视为读取完毕
                if (activeRouteParseFlag && line.startsWith("===")) {
                    activeRouteParseFlag = false;
                    continue;
                }


                // 开始解析活动路由
                if (activeRouteParseFlag) {
                    // 如果活动路由是空、头部则跳过
                    if (line.equals(none) || line.startsWith(networkDestination)) {
                        continue;
                    }

                    String[] split = line.split("\\s+");
                    if (split.length < 5) {
                        continue;
                    }

                    String target = split[0];
                    String mask = split[1];
                    String gateway = split[2];
                    String itfsAddr = split[3];
                    String metric = split[4];


                    NetRoute netRoute = new NetRoute();
                    netRoute.setMask(mask);
                    netRoute.setTarget(target);
                    netRoute.setGateway(gateway);
                    netRoute.setMetric(metric);
                    netRoute.setIp(itfsAddr);
                    netRoute.setType(NetRouteType.TEMPORARY_ROUTE);
//                    NetworkInterface networkInterface = netMap.computeIfAbsent(itfsAddr, k -> NetworkInterfaceHelper.getNetworkInterface(itfsAddr));
//                    if (networkInterface != null){
//                        builder.ifIndex(networkInterface.getIndex());
//                        builder.interfaceName(networkInterface.getName());
//                    }

                    routes.add(netRoute);
                    continue;
                }

                // 开始解析永久路由
                if (persistentRouteParseFlag) {
                    // 如果永久路由是空、且以===开头则退出
                    if (line.equals(none) || line.startsWith("===")) {
                        break;
                    }

                    String[] split = line.split("\\s+");

                    if (split.length < 4 || line.startsWith(networkAddress)) {
                        continue;
                    }


                    String target = split[0];
                    String mask = split[1];
                    String gateway = split[2];
                    String metric = split[3];


                    NetRoute netRoute = new NetRoute();
                    netRoute.setMask(mask);
                    netRoute.setTarget(target);
                    netRoute.setGateway(gateway);
                    netRoute.setMetric(metric);
                    netRoute.setType(NetRouteType.PERMANENT_ROUTE);
//                    NetworkInterface networkInterface = netMap.computeIfAbsent(itfsAddr, k -> NetworkInterfaceHelper.getNetworkInterface(itfsAddr));
//                    if (networkInterface != null){
//                        builder.ifIndex(networkInterface.getIndex());
//                        builder.interfaceName(networkInterface.getName());
//                    }

                    routes.add(netRoute);
                }

            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            return Collections.emptyList();
        }

        return routes;
    }

    /**
     * 获取真实可用的网卡
     *
     * @return 映射
     */
    private Map<NetworkInterface, LinkedHashSet<InetAddress>> getWinNicAdreesMap() {
        return NetworkInterfaceHelper.getNicAdreesMap(networkInterface -> {
            try {
                return !networkInterface.isVirtual() && !networkInterface.isLoopback() && Stream.of("Virtual", "TAP", "VMware", "Bluetooth").noneMatch(s -> networkInterface.getDisplayName().toLowerCase(Locale.ROOT).indexOf(s.toLowerCase(Locale.ROOT)) >= 0);
            } catch (SocketException e) {
                return true;
            }
        }, null);
    }


    private WifiSecureType convertSecurityType(String type) {
        if (type == null || type.isEmpty() || type.equals(wifiLinkInfoSecurityOpen)) {
            return WifiSecureType.OPEN;
        } else {
            if (type.equals(wifiLinkInfoSecurityWPA2)) {
                return WifiSecureType.WPA2;
            } else if (type.equals(wifiLinkInfoSecurityWPA3)) {
                return WifiSecureType.WPA3;
            } else {
                return WifiSecureType.OPEN;
            }
        }
    }

    public static void main(String[] args) throws IOException {
        WinNetworkInterfaceManager winEthNetworkInterfaceManager = new WinNetworkInterfaceManager();

//        winEthNetworkInterfaceManager.configStaticIpAddress("WLAN", "192.168.1.101", "255.255.255.0", "192.168.1.1");
//
//        String s = winEthNetworkInterfaceManager.execCmdAndReturn("");
//        System.out.println(s);

//        winEthNetworkInterfaceManager.delRoute(
//                NetRoute.builder()
//                        .target("192.168.1.0")
//                        .gateway("192.168.1.1")
//                        .mask("255.255.255.0")
//                        .metric("1")
//                        .ifIndex(1)
//                        .build()
//        );

//        List<NetRoute> netIp4Routes = winEthNetworkInterfaceManager.getNetIp4Routes();


//        List<NetworkInterfaceInfo> networkInterfaceInfos = winEthNetworkInterfaceManager.getNetworkInterfaceInfos();
//        System.out.println(networkInterfaceInfos);


//        // 测试 扫描wifi信息指令
//        WifiScanInfo wifiScanInfo = winEthNetworkInterfaceManager.scanWifiInfo("WLAN");
//        System.out.println(wifiScanInfo);


//        // 测试 断开wifi连接
//        String s = winEthNetworkInterfaceManager.disconnectWifi("WLAN");
//        System.out.println(s);

//
//        // 获取wifi配置列表
//        WifiLinkConf wifiProfile = winEthNetworkInterfaceManager.getWifiProfile("WLAN", "21-2-5-3");
//        System.out.println(wifiProfile);

//        // 获取wifi连接信息
//        List<WifiLinkInfo> wifiLinkInfos = winEthNetworkInterfaceManager.getWifiLinkInfos();
//        System.out.println(wifiLinkInfos);

//
//        // 测试删除wifi配置
//        String s1 = winEthNetworkInterfaceManager.delWifiConf("WLAN", "mi 13");
//        System.out.println("删除wifi：" + s1);
//
//

//        // 测试设置wifi配置
//        WifiLinkConf wifiLinkConf = new WifiLinkConf();
//        wifiLinkConf.setAutoConnection(true);
////        wifiLinkConf.setName("mi 13");
//        wifiLinkConf.setSsid("mi 13");
//        wifiLinkConf.setInterfaceName("WLAN");
//        wifiLinkConf.setSecureType(WifiSecureType.OPEN.name());
//        String s = winEthNetworkInterfaceManager.setWifiConf(wifiLinkConf);
//        System.out.println("设置wifi：" + s);
//

//        // 获取wifi配置
//        WifiLinkConf wifiProfile = winEthNetworkInterfaceManager.getWifiProfile("WLAN", "mi 13");
//        System.out.println("wifi配置：" + wifiProfile);


//        // 连接wifi
//        String s2 = winEthNetworkInterfaceManager.connectWifi(wifiLinkConf);
//        System.out.println("连接wifi：" + s2);


//        // 测试忘记连接
//        String s3 = winEthNetworkInterfaceManager.forgetWifi("WLAN","21-2-5-3");
//        System.out.println("忘记连接：" + s3);

//        // 测试断开连接
//        String s4 = winEthNetworkInterfaceManager.disconnectWifi("WLAN");
//        System.out.println("断开连接：" + s4);

//        // 测试禁用wlan
//        String s5 = winEthNetworkInterfaceManager.disableWifi("WLAN");
//        System.out.println("禁用wlan：" + s5);


//       // 测试启用wlan
//        String s6= winEthNetworkInterfaceManager.enableWifi("WLAN");
//        System.out.println("启用wlan：" + s6);

    }
}
